package com.bpmn.flow.listener;

import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.bpmn.common.constant.FlowableConstants;
import com.bpmn.common.enums.TaskOperationEnum;
import com.bpmn.flow.dto.TaskOperationDTO;
import com.bpmn.flow.service.TaskOperationService;
import com.bpmn.utils.ModelUtils;
import com.bpmn.utils.QueryUtils;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.ExtensionAttribute;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.service.delegate.DelegateTask;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 流程任务自动审批跳过的监听器。
 *
 * @author rain
 */
@Slf4j
public class AutoApprovalTaskListener implements TaskListener {

    private static final RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class);

    private static final TaskOperationService taskOperationService = SpringUtil.getBean(TaskOperationService.class);

    /**
     * 流程的发起者等于当前任务的Assignee。
     */
    private static final String EQ_START_USER = "0";
    /**
     * 上一步的提交者等于当前任务的Assignee。
     */
    private static final String EQ_PREV_SUBMIT_USER = "1";
    /**
     * 当前任务的Assignee之前提交过审核。
     */
    private static final String EQ_HISTORIC_SUBMIT_USER = "2";

    @Override
    public void notify(DelegateTask task) {
        UserTask userTask = ModelUtils.getUserTask(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
        List<ExtensionAttribute> attributes = userTask.getAttributes().get(FlowableConstants.USER_TASK_AUTO_SKIP_KEY);
        if (attributes == null || attributes.isEmpty()) {
            log.warn("No attributes found for key: {}", FlowableConstants.USER_TASK_AUTO_SKIP_KEY);
            return;
        }
        Set<String> skipTypes = new HashSet<>(StrUtil.split(attributes.get(0).getValue(), ","));
        if (skipTypes.isEmpty()) {
            log.warn("Skip types set is empty");
            return;
        }
        String assignedUser = task.getAssignee();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        if (StrUtil.isBlank(assignedUser)) {
            return;
        }
        for (String skipType : skipTypes) {
            if (this.verifyAndHandle(task, processInstance, skipType, assignedUser)) {
                return;
            }
        }
    }

    private boolean verifyAndHandle(DelegateTask task, ProcessInstance processInstance, String skipType, String assignedUser) {
        boolean flag = false;
        switch (skipType) {
            case EQ_START_USER:
                // 获取流程发起人
                String startUserId = processInstance.getStartUserId();
                if (ObjectUtil.equal(startUserId, assignedUser)) {
                    flag = true;
                }
                break;
            case EQ_PREV_SUBMIT_USER:
                Object v2 = task.getVariable(FlowableConstants.SUBMIT_USER_VAR);
                if (ObjectUtil.equal(v2, assignedUser)) {
                    flag = true;
                }
                break;
            case EQ_HISTORIC_SUBMIT_USER:
                long count = QueryUtils.hisActivityInstanceQuery(task.getProcessInstanceId()).taskAssignee(task.getAssignee()).finished().count();
                if (count > 0) {
                    flag = true;
                }
                break;
            default:
                break;
        }
        if (flag) {
            TaskOperationDTO taskOperationDTO = new TaskOperationDTO();
            taskOperationDTO.setUserId(task.getAssignee());
            taskOperationDTO.setTaskId(task.getId());
            taskOperationDTO.setOperation(TaskOperationEnum.AGREE.getCode());
            String comment = StrFormatter.format("自动审批。审批人 [{}], 跳过原因 [{}]。", task.getAssignee(), this.getMessageBySkipType(skipType));
            taskOperationDTO.setComment(comment);
            taskOperationService.handleTaskOperation(taskOperationDTO);
        }
        return flag;
    }

    private String getMessageBySkipType(String skipType) {
        return switch (skipType) {
            case EQ_PREV_SUBMIT_USER -> "审批人与上一审批节点处理人相同";
            case EQ_START_USER -> "审批人为发起人";
            case EQ_HISTORIC_SUBMIT_USER -> "审批人审批过";
            default -> "";
        };
    }
}
